package com.bjmashibing.system.io;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class OSFileIO {

    static byte[] data = "123456789\n".getBytes();
    static String path =  "/root/testfileio/out.txt";
    static String davidPath="D:\\temp\\in.txt";
    static String davidPath1="D:\\temp\\out1.txt";



    public static void main(String[] args) throws Exception {


        switch ( args[0]) {
            case "0" :
                testBasicFileIO();
                break;
            case "1":
                testBufferedFileIO();
                break;
            case "2" :
                testRandomAccessFileWrite();
            case "3":
//                whatByteBuffer();
            default:

        }
    }


    /**
     *
     *
     * FileOutputStream out:
     *     out.write
     * FileInputStream in:
     *     in.read
     *
     *
     * @throws Exception
     */
    // 最基本的file写 java.io
    public static  void testBasicFileIO() throws Exception {
        File file = new File(path);
        FileOutputStream out = new FileOutputStream(file);
        while(true){
            Thread.sleep(10);
            out.write(data);

        }

    }

    //  测试buffer文件   IO
    //  jvm  8kB   syscall  write(8KBbyte[])

    public static void testBufferedFileIO() throws Exception {
        File file = new File(path);
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        while(true){
            Thread.sleep(10);
            out.write(data);
        }
    }



    //进入NIO的测试阶段

    /**
     * 与普通io不一样的是，普通io的话只能追加；nio有seek，可以随机位置读写
     * @throws Exception
     */
    public static void testRandomAccessFileWrite() throws  Exception {
        //RandomAccessFile支持"随机访问"的方式，程序可以直接跳转到文件的任意地方来读取数据
        RandomAccessFile raf = new RandomAccessFile(path, "rw");//rw表示读写都满足

        raf.write("hello mashibing\n".getBytes());
        raf.write("hello seanzhou\n".getBytes());
        System.out.println("write------------");
        System.in.read();

        raf.seek(4);
        raf.write("ooxx".getBytes());

        System.out.println("seek---------");
        System.in.read();

        FileChannel rafchannel = raf.getChannel();
        MappedByteBuffer map = rafchannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096);


        map.put("@@@".getBytes());  //不是系统调用  但是数据会到达 内核的pagecache
        System.out.println("map--put--------");
        System.in.read();

//        map.force(); //  flush  要么自己去刷写数据，要么等内核自动刷写数据

        raf.seek(0);

//        ByteBuffer buffer = ByteBuffer.allocate(8192);
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

        int read = rafchannel.read(buffer);   //buffer.put()     读取文件的内容然后put到buffer中
        System.out.println(buffer);
        buffer.flip();
        System.out.println(buffer);

        for (int i = 0; i < buffer.limit(); i++) {
            Thread.sleep(200);
            System.out.print(((char)buffer.get(i)));
        }
    }

    /**
     * 对于buffer的属性进行简单的测试
     */
    @Test
    public  void whatByteBuffer(){

//        ByteBuffer buffer = ByteBuffer.allocate(1024);
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);


        System.out.println("postition: " + buffer.position());
        System.out.println("limit: " +  buffer.limit());
        System.out.println("capacity: " + buffer.capacity());
        System.out.println("mark: " + buffer);

        buffer.put("123".getBytes());

        System.out.println("-------------put:123......");
        System.out.println("mark: " + buffer);

        buffer.flip();   //读写交替

        System.out.println("-------------flip......");
        System.out.println("mark: " + buffer);

        buffer.get();    //get方法是取出第一条数据

        System.out.println("-------------get......");
        System.out.println("mark: " + buffer);

        buffer.compact();   //compact方法是将数据重新补充到buffer的起始读取位置，注意此时的pos和lim的位置

        System.out.println("-------------compact......");
        System.out.println("mark: " + buffer);

        buffer.clear();

        System.out.println("-------------clear......");
        System.out.println("mark: " + buffer);

    }


    @Test
    public void testIO() throws IOException {
        File file=new File(davidPath);
        FileInputStream in=new FileInputStream(file);

        File file1=new File(davidPath1);
        FileOutputStream out=new FileOutputStream(file1);

        int length=0;
        byte[] inChar=new byte[1024];
        while ((length=in.read(inChar))!=-1){
            out.write(inChar);
        }

        in.close();
        out.close();



    }


}
